package com.zmn.oms.task.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.dro.company.CompanyDRO;
import com.zmn.base.common.data.dubbo.interfaces.company.CompanyListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GateTypeConsts;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.dio.coup.scenario.CheckSendCoupScenarioStatusDIO;
import com.zmn.dms.common.dio.coup.scenario.SendCoupScenarioDIO;
import com.zmn.dms.common.dro.coup.scenario.SendCoupScenarioDRO;
import com.zmn.dms.common.enums.DiscountTypeEnums;
import com.zmn.dms.common.enums.UserTypeEnums;
import com.zmn.dms.common.enums.coup.CoupScenarioSendNodeEnums;
import com.zmn.dms.dubbo.interfaces.coup.scenario.CoupScenarioModifyRemoteService;
import com.zmn.manager.mq.annotation.AliyunMQHandler;
import com.zmn.manager.mq.annotation.AliyunMQListener;
import com.zmn.manager.mq.constant.MqTopicConsts;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.manager.redis.lock.DistributedLock;
import com.zmn.manager.redis.lock.DistributedLockUtils;
import com.zmn.oms.business.interfaces.conf.channel.ConfOrderChannelBService;
import com.zmn.oms.business.interfaces.operator.OrderWorkOperatorBService;
import com.zmn.oms.business.interfaces.order.OrderServiceReasonBService;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountCalcBService;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.business.interfaces.user.OrderUserBService;
import com.zmn.oms.business.interfaces.work.OrderWorkAmountBService;
import com.zmn.oms.business.interfaces.work.distribute.DistributeTimeoutBservice;
import com.zmn.oms.business.interfaces.work.epidemiccontrol.OrderWorkEpidemicControlBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dro.conf.channel.ConfOrderChannelDRO;
import com.zmn.oms.common.dto.QueueOrderNodeNotifyDTO;
import com.zmn.oms.common.enums.ConfChannelWorkOrderTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.model.bo.orderamount.OrderAmountCalcBO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.dto.changerecord.ChangeServCategDTO;
import com.zmn.oms.model.dto.remark.OrderRemarkDetailDTO;
import com.zmn.oms.model.dto.work.modify.must.ZsCancelDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.work.OrderAssignVO;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.datasync.ElasticSearchDataSyncService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.youshu.YouShuConsts;
import com.zmn.oms.third.youshu.service.YouShuService;
import com.zmn.oms.zmn.business.interfaces.discount.ChannelDiscountService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkAssignBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.ZsNormalWorkBService;
import com.zmn.track.common.constant.apply.cancel.CancelApplyConsts;
import com.zmn.track.dubbo.dio.apply.cancel.CheckAllowApplyCancelDIO;
import com.zmn.track.dubbo.dio.apply.cancel.SubmitApplyCancelDIO;
import com.zmn.track.dubbo.dro.apply.cancel.CheckAllowApplyCancelDRO;
import com.zmn.track.dubbo.interfaces.apply.cancel.OrderCancelApplyListRemoteService;
import com.zmn.track.dubbo.interfaces.apply.cancel.OrderCancelApplyModifyRemoteService;
import com.zmn.uuc.common.constant.DubboConsts;
import com.zmn.uuc.common.dro.user.UserBaseDRO;
import com.zmn.uuc.dubbo.interfaces.user.UserListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.SQLTransientConnectionException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.zmn.consts.GateTypeConsts.GATE_TYPE_MAP;

/**
 * 类描述：工单事件节点监听
 *
 * @author heciqi
 * @date 2021/6/8 10:40
 */
@Slf4j
@AliyunMQListener(topic = "${spring.mq.topic.oms}")
@Component
public class OrderWorkNodeListener {

    @Resource
    private OrderWorkOperatorBService orderWorkOperatorBService;
    @Autowired
    private DistributeTimeoutBservice distributeTimeoutBservice;
    @Autowired
    private OrderUserBService orderUserBService;
    @Autowired
    private OrderServiceReasonBService orderServiceReasonBService;
    @Autowired
    private ChannelDiscountService channelDiscountService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private ZsNormalWorkBService zsNormalWorkBService;
    @Resource
    private OrderProductService orderProductService;
    @Resource
    private ElasticSearchDataSyncService elasticSearchDataSyncService;
    @Resource
    private OrderWorkService orderWorkService;
    @Resource
    private YouShuService youShuService;
    @Resource
    private ConfOrderChannelBService confOrderChannelBService;
    @Autowired
    private OrderWorkAssignBService orderWorkAssignBService;
    @Autowired
    private OrderChangeRecordService orderChangeRecordService;
    @Autowired
    private OrderDiscountCalcBService orderDiscountCalcBService;
    @Autowired
    private OrderDiscountService orderDiscountService;
    @Autowired
    private OrderAmountCalcBService orderAmountCalcBService;
    @Autowired
    private OrderWorkAmountBService orderWorkAmountBService;
    @Autowired
    private OrderWorkEpidemicControlBService workEpidemicControlBService;

    @Resource
    ZmnMQSender zmnMQSender;


    @DubboReference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private CoupScenarioModifyRemoteService coupScenarioModifyRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private CompanyListRemoteService companyListRemoteService;
    @DubboReference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private OrderCancelApplyListRemoteService orderCancelApplyListRemoteService;
    @DubboReference(version = com.zmn.track.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
    private OrderCancelApplyModifyRemoteService orderCancelApplyModifyRemoteService;
    @DubboReference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private UserListRemoteService userListRemoteService;

    @NacosValue(value = "${order.unable.service.cancel.reason.id:21}", autoRefreshed = true)
    private Integer cancelReasonId;

    /**
     * 下单
     *
     * @param message
     */
    @AliyunMQHandler(tags = MessageQueueTagConsts.ORDER_ADD)
    public void addOrder(String message) {
        log.debug("下单监听[{}]", message);
        QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);

        // 检查是否能够直接
        try {
            checkCancel(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 发送优惠券
        /*try {
            this.sendCoupon(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }*/

        // 定金抵扣代金券发放
        try {
            this.sendCoupon(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 更新下单人部门和组织架构
        try {
            orderWorkOperatorBService.addOperatorByNodeNotify(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 发起派单超时检查
        try {
            distributeTimeoutBservice.addTimeoutCheck(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 网格是否绑定工程师
        try {
            orderServiceReasonBService.isSatisfyGrid(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 腾讯有数
        try {
            this.sendOrderInfoToYouShu(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 美团预约下单
        try {
            channelDiscountService.addMeiTuanChannelDiscount(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error("[{}]美团预约订单插入优惠失败：【{}】", queueOrderNodeNotifyDTO.getOrderId(), e.getMessage());
            log.error(e.getMessage(), e);
        }

        // 保存订单下单服务分类
        try {
            this.recordOrderServCateg(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error("[{}]记录新单服务分类：【{}】", queueOrderNodeNotifyDTO.getOrderId(), e.getMessage());
            log.error(e.getMessage(), e);
        }

        // 存储疫情信息
        try {
            workEpidemicControlBService.save(queueOrderNodeNotifyDTO, OrderLogConsts.ORDER_LOG_TYPE_INPUT);
        } catch (Exception e) {
            log.error("下单疫情信息存储  orderId=[{}]  error=[{}]", queueOrderNodeNotifyDTO.getOrderId(), e);
        }
    }

    /**
     * 派单
     *
     * @param message
     */
    @AliyunMQHandler(tags = PublishTagConsts.PUBLISH_ORDER_DISTRIBUTE)
    public void orderDistribute(String message) {
        log.debug("派单监听[{}]", message);
        QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);
    }

    /**
     * 上门
     *
     * @param message
     */
    @AliyunMQHandler(tags = MessageQueueTagConsts.ORDER_VISIT)
    public void visitOrder(String message) {
        log.debug("上门监听[{}]", message);
        QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);
        // 上门后，如果是临时用户转正，需要转正处理
        try {
            orderUserBService.regularizedUserByOrderId(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 腾讯有数
        try {
            this.sendOrderInfoToYouShu(queueOrderNodeNotifyDTO);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 订单完成操作
     *
     * @param message
     */
    @AliyunMQHandler(tags = MessageQueueTagConsts.ORDER_COMPLETE)
    public void orderComplete(String message) {
        log.debug("#OrderWorkNodeListener#complete message:[{}]", message);
        QueueOrderNodeNotifyDTO dto = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);

        try {
            if (Objects.isNull(dto)) {
                return;
            }
            // 补偿子公司
            this.compensatesOrderWorkCompany(dto.getOrderId(), dto.getWorkId());

            elasticSearchDataSyncService.syncPayIndex(dto.getOrderId());
        } catch (Exception e) {
            log.error("#OrderWorkNodeListener#complete重建索引消费失败 {}", e.getMessage(), e);
            if (e instanceof SQLTransientConnectionException) {
                log.error("数据库连接错误");
            }
        }

        // 腾讯有数
        try {
            this.sendOrderInfoToYouShu(dto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 存储疫情信息
        try {
            workEpidemicControlBService.save(dto, OrderLogConsts.ORDER_LOG_TYPE_COMPLETE);
        } catch (Exception e) {
            log.error("订单完成疫情信息存储  orderId=[{}]  error=[{}]", dto.getOrderId(), e);
        }
    }

    /**
     * 订单收单操作
     *
     * @param message
     */
    @AliyunMQHandler(tags = MessageQueueTagConsts.ORDER_CHECKOUT)
    public void orderCheckout(String message) {
        log.debug("#OrderWorkNodeListener#orderCheckout message:[{}]", message);
        try {
            QueueOrderNodeNotifyDTO dto = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);
            if (Objects.isNull(dto)) {
                return;
            }
            elasticSearchDataSyncService.syncPayIndex(dto.getOrderId());
        } catch (Exception e) {
            log.error("#oms#OrderWorkNodeListenerchange#重建索引消费失败 {}", e.getMessage(), e);
            if (e instanceof SQLTransientConnectionException) {
                log.error("数据库连接错误");
            }
        }
    }

    /**
     * 订单算账操作
     *
     * @param message
     */
    @AliyunMQHandler(tags = MessageQueueTagConsts.ORDER_ACCOUNT)
    public void orderAccount(String message) {
        log.debug("#OrderWorkNodeListener#orderAccount message:[{}]", message);
        QueueOrderNodeNotifyDTO dto = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);
        try {
            if (Objects.isNull(dto)) {
                return;
            }
            elasticSearchDataSyncService.syncPayIndex(dto.getOrderId());
        } catch (Exception e) {
            log.error("#oms#OrderWorkNodeListenerchange#重建索引消费失败 {}", e.getMessage(), e);
            if (e instanceof SQLTransientConnectionException) {
                log.error("数据库连接错误");
            }
        }

        // 腾讯有数
        try {
            if (Objects.equals(dto.getType(), OrderConsts.ORDER_TYPE_REFUND)) {
                this.sendOrderInfoToYouShu(dto);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 订单取消操作
     *
     * @param message
     */
    @AliyunMQHandler(tags = PublishTagConsts.PUBLISH_ORDER_CANCEL)
    public void orderCancel(String message) {
        log.debug("#OrderWorkNodeListener#orderCancel message:[{}]", message);
        QueueOrderNodeNotifyDTO dto = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);

        // 腾讯有数
        try {
            this.sendOrderInfoToYouShu(dto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 存储疫情信息
        try {
            workEpidemicControlBService.save(dto, OrderLogConsts.ORDER_LOG_TYPE_CANCEL);
        } catch (Exception e) {
            log.error("订单取消疫情信息存储  orderId=[{}]  error=[{}]", dto.getOrderId(), e);
        }
    }

    /**
     * 订单修改操作
     *
     * @param message
     */
    @AliyunMQHandler(tags = PublishTagConsts.PUBLISH_ORDER_UPDATE)
    public void orderUpdate(String message) {
        log.debug("#OrderWorkNodeListener#orderUpdate message:[{}]", message);
        QueueOrderNodeNotifyDTO dto = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);

        // 记录服务分类修改
        try {
            this.recordOrderServCateg(dto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 重新判断手机号是否为VVIP
        try {
            this.rejudgeVVIP(dto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        // 存储疫情信息
        try {
            workEpidemicControlBService.save(dto, OrderLogConsts.ORDER_LOG_TYPE_UPDATE);
        } catch (Exception e) {
            log.error("订单修改疫情信息存储  orderId=[{}]  error=[{}]", dto.getOrderId(), e);
        }
    }

    /**
     * 订单修改产品操作
     *
     * @param message
     */
    @AliyunMQHandler(tags = PublishTagConsts.PUBLISH_ORDER_UPDATE_PRODUCT)
    public void orderUpdateProduct(String message) {
        log.debug("#OrderWorkNodeListener#orderUpdateProduct message:[{}]", message);
        QueueOrderNodeNotifyDTO dto = JSON.parseObject(message, QueueOrderNodeNotifyDTO.class);

        // 渠道订单修改产品，作废渠道优惠券删除优惠信息
        Integer apiGateType = GATE_TYPE_MAP.get(dto.getReceiveEntranceId());
        if (Objects.equals(apiGateType, GateTypeConsts.GATE_TYPE_API)) {
            this.absChannelDiscountAndUpdateWorkAmount(dto.getOrderId(), dto.getWorkId());
        }
    }

    /**
     * 作废渠道优惠券、更新工单金额
     *
     * @param orderId
     * @param workId
     */
    private void absChannelDiscountAndUpdateWorkAmount(Long orderId, Long workId) {
        List<String> channelDiscountCodes = orderDiscountService.listByOrderId(orderId)
                .stream().filter(e -> Objects.equals(e.getCateg(), DiscountTypeEnums.DISCOUNT_CHANNEL.getSubType()))
                .map(e -> e.getItemCode()).collect(Collectors.toList());
        log.info("修改产品作废渠道优惠券-->{}", channelDiscountCodes);
        if (CollectionUtil.isNotNullOrEmpty(channelDiscountCodes)) {
            try {
                // 作废优惠券
                orderDiscountCalcBService.obsDiscountItemCodes(channelDiscountCodes, orderId);
                // 删除优惠信息
                OrderDiscount orderDiscount = new OrderDiscount();
                orderDiscount.setOrderId(orderId);
                orderDiscount.setCateg(DiscountTypeEnums.DISCOUNT_CHANNEL.getSubType());
                orderDiscountService.deleteByOrderIdAndCateg(orderDiscount);
                // 重新计算工单金额
                OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);
                ReCalcOrderAmountDIO reCalcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
                OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcAmount(reCalcOrderAmountDIO);
                orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, orderWork);
            } catch (OmsBaseException e) {
                log.error(e.getMessage(), e);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }
    /**
     * 新单发送优惠券
     *
     * @param queueOrderNodeNotifyDTO
     */
    private void sendCoupon(QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO) {
        if (!Objects.equals(queueOrderNodeNotifyDTO.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        // 检查下单是否发优惠券
        CheckSendCoupScenarioStatusDIO checkSendCoupScenarioStatusDIO = new CheckSendCoupScenarioStatusDIO();
        checkSendCoupScenarioStatusDIO.setSendNode(CoupScenarioSendNodeEnums.CREATE_ORDER_SEND.getKey());
        checkSendCoupScenarioStatusDIO.setChannelId(queueOrderNodeNotifyDTO.getChannelId());
        checkSendCoupScenarioStatusDIO.setCityId(queueOrderNodeNotifyDTO.getCityId());
        checkSendCoupScenarioStatusDIO.setUserType(UserTypeEnums.PERSONAL_USER.getKey());
        checkSendCoupScenarioStatusDIO.setUserId(queueOrderNodeNotifyDTO.getUserId());
        checkSendCoupScenarioStatusDIO.setOrderEntrance(queueOrderNodeNotifyDTO.getReceiveEntranceId());
        ResponseDTO<Boolean> booleanResponseDTO = coupScenarioModifyRemoteService.checkSendCoupScenarioStatus(checkSendCoupScenarioStatusDIO);
        log.info("是否能发送优惠券coupScenarioModifyRemoteService#checkSendCoupScenarioStatus入参[{}]出参[{}]", checkSendCoupScenarioStatusDIO, booleanResponseDTO);

        // 发放优惠券
        if (booleanResponseDTO.isSuccess() && booleanResponseDTO.getData()) {
            SendCoupScenarioDIO sendCoupScenarioDIO = new SendCoupScenarioDIO();
            sendCoupScenarioDIO.setSendNode(CoupScenarioSendNodeEnums.CREATE_ORDER_SEND.getKey());
            sendCoupScenarioDIO.setChannelId(queueOrderNodeNotifyDTO.getChannelId());
            sendCoupScenarioDIO.setCityId(queueOrderNodeNotifyDTO.getCityId());
            sendCoupScenarioDIO.setUserType(UserTypeEnums.PERSONAL_USER.getKey());
            sendCoupScenarioDIO.setUserId(queueOrderNodeNotifyDTO.getUserId());
            sendCoupScenarioDIO.setOrderEntrance(queueOrderNodeNotifyDTO.getReceiveEntranceId());
            ResponseDTO<SendCoupScenarioDRO> sendCoupScenarioDROResponseDTO = coupScenarioModifyRemoteService.sendCoupScenarioCoupToUser(sendCoupScenarioDIO);
            log.info("下单发送优惠券coupScenarioModifyRemoteService#sendCoupScenarioCoupToUser入参[{}]出参[{}]",
                    sendCoupScenarioDIO, JSON.toJSONString(sendCoupScenarioDROResponseDTO));
        }
    }

    /**
     * 检查是否能够直接取消
     *
     * @param queueOrderNodeNotifyDTO
     */
    private void checkCancel(QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO) throws OmsBaseException {
        // 非新单不处理
        if (!Objects.equals(queueOrderNodeNotifyDTO.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        ConfOrderChannelDRO confOrderChannelDRO = confOrderChannelBService.getByChannelId(queueOrderNodeNotifyDTO.getChannelId());
        if (Objects.nonNull(confOrderChannelDRO)) {
            // 特殊渠道
            if (Objects.equals(confOrderChannelDRO.getSupportBacktracking(), GlobalConsts.NO)) {
                return;
            }
            // 渠道配置不能自动取消
            boolean isAutoCancel = StringUtil.isNotBlank(confOrderChannelDRO.getWorkOrderCancelType()) &&
                    StringUtil.convertStrsToList(confOrderChannelDRO.getWorkOrderCancelType())
                            .contains(ConfChannelWorkOrderTypeEnum.CONSTS_AUTOCANCEL);
            if (!isAutoCancel) {
                return;
            }
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());
        if (Objects.isNull(orderWork)) {
            orderWork = orderWorkService.findOrderWorkByKeySrcMaster(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());
        }

        // 订单详情
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(queueOrderNodeNotifyDTO.getOrderId());

        // 街道为空不自动取消
        if (StringUtil.isBlank(orderDetail.getStreet())) {
            return;
        }

        List<OrderProduct> productList = orderProductService.listOrderProductByOrderId(queueOrderNodeNotifyDTO.getOrderId());
        if (CollectionUtils.isNotEmpty(productList)) {
            boolean anyMatch = productList.stream().anyMatch(item ->
                    Objects.equals(10310, item.getProductId()) || Objects.equals(10310, item.getShowProductId()));
            if(anyMatch){
                return;
            }
        }

        // 平台直派 or 服务商派单
        if (Objects.equals(orderWork.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {

            // 新单没有网格，会走无网格派单
            if (Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                    && Objects.equals(orderDetail.getGridId(), GlobalConsts.NONE)) {
                return;
            }

            // 如果是家修匠-无法承接线索-30分钟后再判断是否取消
            if (Objects.equals(orderDetail.getGridManageCompanyId(), CompanyConsts.ZMN_JXJ_MANAGE_COMPANY_ID)) {
                long time = System.currentTimeMillis() + 1000 * 60 * 5;
                String key = String.format("auto-cancel-%s", queueOrderNodeNotifyDTO.getOrderId());
                JSONObject jb = new JSONObject();
                jb.put("orderId", queueOrderNodeNotifyDTO.getOrderId());
                jb.put("workId", queueOrderNodeNotifyDTO.getWorkId());
                log.info("发送家修匠延时取消消息：tag:{},key:{},message:{}", OmsMqTagConsts.ORDER_WORK_JXJ_DELAYED_CANCEL_TAG, key, jb.toJSONString());
                zmnMQSender.sendWithStartDeliverTime(MqTopicConsts.ZMN_TOPIC_OMS, OmsMqTagConsts.ORDER_WORK_JXJ_DELAYED_CANCEL_TAG, key, jb.toJSONString(), time);
                return;
            } else {
                // 行政服务商不是无法承接线索，不取消
                if (!Objects.equals(orderDetail.getGridManageCompanyId(), CompanyConsts.ZMN_UNABLE_SERVICE_MANAGE_COMPANY_ID)) {
                    return;
                }
            }
        } else {
            List<OrderAssignVO> assignList = orderWorkAssignBService.listAssignCompany(orderWork, orderDetail, false);
            // 服务商派单有服务商可服务，不取消
            if (CollectionUtil.isNotNullOrEmpty(assignList)) {
                return;
            }
        }

        // 是否真实取消
        boolean isRealCancel = true;

        // 判断是否允许申请
        CheckAllowApplyCancelDIO applyCancelDIO = CheckAllowApplyCancelDIO
                .builder()
                .orderId(queueOrderNodeNotifyDTO.getOrderId())
                .workId(queueOrderNodeNotifyDTO.getWorkId())
                .applySource(CancelApplyConsts.CANCEL_APPLY_SOURCE_SYS_AUTO)
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .channelId(orderWork.getChannelId())
                .servCategId(orderWork.getServCategId())
                .showCategId(orderWork.getShowCategId())
                .build();
        log.info("{} 检查是否允许申请取消入参 applyCancelDIO={}", queueOrderNodeNotifyDTO.getWorkId(), applyCancelDIO);
        ResponseDTO<CheckAllowApplyCancelDRO> checkAllowApplyCancelDROResponseDTO = orderCancelApplyListRemoteService.checkAllowApplyCancel(applyCancelDIO);
        log.info("{} 检查是否允许申请取消出参 checkAllowApplyCancelDROResponseDTO={}", queueOrderNodeNotifyDTO.getWorkId(), checkAllowApplyCancelDROResponseDTO);
        if (!checkAllowApplyCancelDROResponseDTO.isSuccess() || Objects.isNull(checkAllowApplyCancelDROResponseDTO.getData())) {
            isRealCancel = false;
        }
        CheckAllowApplyCancelDRO dro = checkAllowApplyCancelDROResponseDTO.getData();
        if (dro.isAllowApply()) {
            isRealCancel = false;
        }

        if (isRealCancel) {
            ZsCancelDTO zsCancelDTO = new ZsCancelDTO();
            zsCancelDTO.setOrderId(queueOrderNodeNotifyDTO.getOrderId());
            zsCancelDTO.setWorkId(queueOrderNodeNotifyDTO.getWorkId());
            List<OrderRemarkDetailDTO> detailDTOList = Lists.newArrayList();
            OrderRemarkDetailDTO dto = new OrderRemarkDetailDTO();
            dto.setMapId(cancelReasonId);
            dto.setMapName("无法服务线索，系统取消工单");
            detailDTOList.add(dto);
            zsCancelDTO.setDetailDTOList(detailDTOList);

            // 操作人信息
            zsCancelDTO.setOperator(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
            zsCancelDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            zsCancelDTO.setOperatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
            log.info("无法服务线索，系统取消工单 入参：{}", JSON.toJSONString(zsCancelDTO));
            zsNormalWorkBService.saveCancel(zsCancelDTO);
        }else {
            // 发起取消申请
            Map<Integer, String> reasonMap = Maps.newHashMap();
            reasonMap.put(cancelReasonId, "无法服务线索，系统取消工单");
            SubmitApplyCancelDIO submitApplyCancelDIO = SubmitApplyCancelDIO
                    .builder()
                    .orderId(queueOrderNodeNotifyDTO.getOrderId())
                    .workId(queueOrderNodeNotifyDTO.getWorkId())
                    .applySource(CancelApplyConsts.CANCEL_APPLY_SOURCE_SYS_AUTO)
                    .operator(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM))
                    .operatorId((long) GlobalConsts.OPERATE_USER_TYPE_SYSTEM)
                    .operatorType(GlobalConsts.OPERATE_USER_TYPE_SYSTEM)
                    .reasonMap(reasonMap)
                    .build();
            log.info("{} 提交取消申请#submitApplyCancel submitApplyCancelDIO={}", queueOrderNodeNotifyDTO.getWorkId(), submitApplyCancelDIO);
            ResponseDTO responseDTO = orderCancelApplyModifyRemoteService.submitApplyCancel(submitApplyCancelDIO);
            log.info("{} 提交取消申请#submitApplyCancel responseDTO={}", queueOrderNodeNotifyDTO.getWorkId(), responseDTO);
        }
    }

    /**
     * 新单数据上报至有数
     *
     * @param queueOrderNodeNotifyDTO
     */
    private void sendOrderInfoToYouShu(QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO) {
        try {
            // 避免重复消费
            String redisKey = String.format(LockConsts.LOCK_ORDER_YOUSHU, queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getStatus());
            DistributedLock lock = DistributedLockUtils.build(redisKey, LockConsts.LOCK_VALID_TIME);
            if (lock.lock()) {
                // 剔除测试
                if (Objects.equals(queueOrderNodeNotifyDTO.getTest(), GlobalConsts.YES)) {
                    return;
                }

                // 剔除非新单和退款单
                if (!(Objects.equals(queueOrderNodeNotifyDTO.getType(), OrderConsts.ORDER_TYPE_NEW) ||
                        Objects.equals(queueOrderNodeNotifyDTO.getType(), OrderConsts.ORDER_TYPE_REFUND))) {
                    return;
                }

                // 非指定渠道不上报
                if (!YouShuConsts.PUSH_CHANNEL_SET.contains(queueOrderNodeNotifyDTO.getChannelId())) {
                    return;
                }

                youShuService.sendAddOrder(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());
            }
        } catch (OmsBaseException e) {
            log.error("orderId={} 新单数据上报至有数失败:{}", queueOrderNodeNotifyDTO.getOrderId(), e);
        }
    }

    /**
     * 补偿缺失的订单子公司数据
     *
     * @param orderId
     * @param workId
     */
    private void compensatesOrderWorkCompany(Long orderId, Long workId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (NumberUtil.isNotNullOrZero(orderWork.getCompanyId())) {
            return;
        }

        log.info("[{}]订单完成---无子公司数据", orderId);
        if (NumberUtil.isNullOrZero(orderWork.getManageCompanyId())) {
            log.error("[{}]订单完成---无服务公司数据", orderId);
            return;
        }

        CompanyDRO companyDRO = companyListRemoteService.getCompanyDROById(orderWork.getManageCompanyId()).getData();
        log.info("baseCompanyListRemoteService#getCompanyByCompanyId[{}]出参[{}]", orderWork.getManageCompanyId(), JSON.toJSONString(companyDRO));
        if (Objects.isNull(companyDRO)) {
            return;
        }
        log.info("[{}]订单完成--补偿子公司数据", orderId);
        OrderWork upOrderWork = new OrderWork();
        upOrderWork.setOrderId(orderId);
        upOrderWork.setWorkId(workId);
        upOrderWork.setCompanyId(companyDRO.getSubCompanyId());
        upOrderWork.setCompanyName(companyDRO.getSubCompanyName());
        orderWorkService.updateOrderWorkCompany(upOrderWork);
    }

    /**
     * 记录新单服务分类
     *
     * @param queueOrderNodeNotifyDTO
     */
    private void recordOrderServCateg(QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO) throws OmsBaseException {
        ChangeServCategDTO dto = new ChangeServCategDTO();
        dto.setOrderId(queueOrderNodeNotifyDTO.getOrderId());
        dto.setInputServCategId(queueOrderNodeNotifyDTO.getServCategId());
        dto.setCurrServCategId(queueOrderNodeNotifyDTO.getServCategId());
        dto.setOperateTime(DateUtil.getNow());
        dto.setOperatorId(queueOrderNodeNotifyDTO.getOperatorId());
        dto.setOperatorName(queueOrderNodeNotifyDTO.getOperator());
        dto.setOperatorType(queueOrderNodeNotifyDTO.getOperatorType());
        orderChangeRecordService.updateChangeServCateg(dto);
    }

    /**
     * 记录新单服务分类
     *
     * @param queueOrderNodeNotifyDTO
     */
    private void rejudgeVVIP(QueueOrderNodeNotifyDTO queueOrderNodeNotifyDTO) throws OmsBaseException {
        if (NumberUtil.isNullOrZero(queueOrderNodeNotifyDTO.getOrderId()) || NumberUtil.isNullOrZero(queueOrderNodeNotifyDTO.getWorkId())) {
            return;
        }
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(queueOrderNodeNotifyDTO.getOrderId(), queueOrderNodeNotifyDTO.getWorkId());

        if (Objects.isNull(orderWork) || !Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(queueOrderNodeNotifyDTO.getOrderId());
        if (Objects.isNull(orderDetail)) {
            return;
        }
        Integer isVVIP = isVVIPByMobile(orderDetail.getTelephone()) || isVVIPByMobile(orderDetail.getTelephone2()) || isVVIPByMobile(orderDetail.getTelephone3()) ? GlobalConsts.YES : GlobalConsts.NO;

        if (!Objects.equals(isVVIP, orderDetail.getVvip())) {
            // 如果结果变更 更新
            OrderDetail updateDetail = new OrderDetail();
            updateDetail.setDetailId(queueOrderNodeNotifyDTO.getOrderId());
            updateDetail.setVvip(isVVIP);
            updateDetail.setUpdater("系统");
            updateDetail.setUpdateTime(DateUtil.getNow());
            orderDetailService.updateOrderDetailByKey(updateDetail);
        }
    }

    private boolean isVVIPByMobile(String mobile) {
        if (StringUtil.isBlank(mobile)) {
            return false;
        }

        ResponseDTO<List<UserBaseDRO>> userResponse = userListRemoteService.listUserByMobile(mobile, false);
        if (!userResponse.isSuccess() || CollectionUtil.isNullOrEmpty(userResponse.getData())) {
            return false;
        }

        return userResponse.getData().stream().anyMatch(userBaseDRO -> Objects.equals(userBaseDRO.getVvip(), GlobalConsts.YES));
    }


}
